package org.anachronos.jeep.ui.attach;

import java.util.EnumMap;
import java.util.List;

import org.anachronos.jeep.core.attach.VirtualMachineAttachement;
import org.anachronos.jeep.core.attach.VirtualMachineRemoteControl;
import org.anachronos.jeep.core.attach.VirtualMachineAttachement.State;
import org.anachronos.jeep.ui.JeepUiPlugin;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.part.ViewPart;

public class VirtualMachineAttachementsView extends ViewPart {
	public static final String ID = "org.anachronos.jeep.rcp.view.vms";

	private TableViewer viewer;

	private final class ViewComparator extends ViewerComparator {
		@Override
		public int compare(final Viewer viewer, final Object e1, final Object e2) {
			final VirtualMachineAttachement vmAttachment1 = (VirtualMachineAttachement) e1;
			final VirtualMachineAttachement vmAttachment2 = (VirtualMachineAttachement) e2;
			return vmAttachment1.getId().compareTo(vmAttachment2.getId());
		}
	}

	class ViewContentProvider implements IStructuredContentProvider {
		private List<VirtualMachineAttachement> vmAttachements;
		
		@SuppressWarnings("unchecked")
		public void inputChanged(final Viewer v, final Object oldInput, final Object newInput) {
			vmAttachements = (List<VirtualMachineAttachement>) newInput;
		}

		public void dispose() {
		}

		public Object[] getElements(final Object parent) {
			final Object[] array = vmAttachements.toArray();
			return array;
		}
	}

	class ViewLabelProvider extends LabelProvider implements
			ITableLabelProvider {
		
		private final EnumMap<State, Image> stateIcons = new EnumMap<State, Image>(State.class);

		public ViewLabelProvider() {
			initStateIcons();
		}

		private void initStateIcons() {
			addStateIcon(State.DETACHED, "icons/computer.png");
			addStateIcon(State.ATTACHED, "icons/computer_link.png");
			addStateIcon(State.PROFILING, "icons/clock_go.png");
		}

		private void addStateIcon(final State state, final String path) {
			final Image stateIcon = JeepUiPlugin.getImageDescriptor(path).createImage();
			stateIcons.put(state, stateIcon);
		}

		@Override
		public void dispose() {
			disposeIcons();
			super.dispose();
		}

		private void disposeIcons() {
			for (final Image stateIcon : stateIcons.values()) {
				stateIcon.dispose();
			}
		}
		
		public String getColumnText(final Object obj, final int index) {
			final VirtualMachineAttachement vmAttachment = (VirtualMachineAttachement) obj;
			switch (index) {
			case 1:
				return vmAttachment.getId();
			case 2:
				return vmAttachment.getName();
			default:
				return null;
			}
		}

		public Image getColumnImage(final Object obj, final int index) {
			final VirtualMachineAttachement vmAttachement = (VirtualMachineAttachement) obj;
			return index == 0 ? getStateIcon(vmAttachement) : null;
		}
		
		private Image getStateIcon(final VirtualMachineAttachement vmAttachement) {
			return stateIcons.get(vmAttachement.getState());
		}
	}
	
	public void setInput(final Object input) {
		viewer.setInput(input);
	}
	
	public void createPartControl(Composite parent) {
		final TableColumnLayout layout = new TableColumnLayout();
		parent.setLayout(layout);
		
		viewer = new TableViewer(parent, SWT.SINGLE | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION);
		final Table table = viewer.getTable();

		final TableColumn iconColumn = createColumn(null, false);
		layout.setColumnData(iconColumn, new ColumnPixelData(24));

		final TableColumn idColumn = createColumn("Id", false);
		layout.setColumnData(idColumn, new ColumnPixelData(50));

		final TableColumn nameColumn = createColumn("Name", true);
		layout.setColumnData(nameColumn, new ColumnWeightData(60, 280, true));

		table.setHeaderVisible(true);
		
		viewer.setContentProvider(new ViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		viewer.setComparator(new ViewComparator());
		viewer.addFilter(new ViewerFilter() {
			@Override
			public boolean select(Viewer viewer, Object parentElement, Object element) {
				final ICommandService commandService = 
					(ICommandService) getSite().getService(ICommandService.class);
				final boolean filterOwnJVMs = (Boolean) commandService.getCommand("org.anachronos.jeep.ui.command.filterOwnJVMs")
					.getState("org.eclipse.ui.commands.toggleState").getValue();
				final VirtualMachineAttachement vmAttachement = 
					(VirtualMachineAttachement) element;
				final boolean isOwnJvm = 
					vmAttachement.getSystemProperties().containsKey(VirtualMachineRemoteControl.OWN_JVMS_MARKER);
				return !isOwnJvm || !filterOwnJVMs;
			}
		});
		final VirtualMachineRemoteControl virtualMachineRemoteControl = 
			JeepUiPlugin.getDefault().getVirtualMachineRemoteControl();
		final List<VirtualMachineAttachement> list = virtualMachineRemoteControl.list();
		viewer.setInput(list);
		
		final MenuManager menuManager = new MenuManager();
		menuManager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
        table.setMenu(menuManager.createContextMenu(table));
        getSite().registerContextMenu(menuManager, viewer);
        
        getSite().setSelectionProvider(viewer);
	}

	private TableColumn createColumn(final String text, final boolean resizable) {
		final TableColumn column = new TableColumn(viewer.getTable(), SWT.LEFT);
		if (text != null) {
			column.setText(text);
		}
		column.setResizable(resizable);
		column.setMoveable(resizable);
		return column;
	}
	
	public void setFocus() {
		viewer.getControl().setFocus();
	}
}